﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RPGXEngine.Networking
{
    public abstract class NetworkMessage : INetworkMessageObject
    {
        #region Properties

        public int MessageSize
        {
            get
            {
                return this.GetMessageSize();
            }
        }

        public abstract MessageTypes Type
        {
            get;
        }

        public ClientDestinationInfomation DestinationInformation
        {
            get { return _destinationInformation; }
            set { _destinationInformation = value; }
        }
        private ClientDestinationInfomation _destinationInformation = new ClientDestinationInfomation();

        #endregion

        #region Public Methods

        public virtual int GetMessageSize()
        {
            int size = 0;

            size += sizeof(int); // Type
            size += this.DestinationInformation.GetMessageSize();

            return size;
        }

        public void FromBytes(byte[] bytes)
        {
            this.FromBytes(bytes, 0);
        }

        public virtual byte[] GetMessageAsBytes()
        {
            List<byte> bytes = new List<byte>();

            bytes.AddRange(BitConverter.GetBytes(this.GetMessageSize()));
            bytes.AddRange(BitConverter.GetBytes((int)this.Type));

            bytes.AddRange(this.DestinationInformation.GetMessageAsBytes());

            return bytes.ToArray();
        }

        public virtual int FromBytes(byte[] bytes, int index)
        {
            int messageSize = BitConverter.ToInt32(bytes, index);
            index += sizeof(int);

            if (messageSize != this.MessageSize)
                throw new InvalidOperationException(String.Format("Expected message size: {0} - Actual message size: {1}",
                    this.MessageSize,
                    messageSize));

            MessageTypes type = (MessageTypes)BitConverter.ToInt32(bytes, index);
            index += sizeof(int);

            if (type != this.Type)
                throw new InvalidOperationException(String.Format("Expected message type: {0} - Actual message type: {1}",
                    this.Type,
                    type));

            index = this.DestinationInformation.FromBytes(bytes, index);

            return index;
        }

        #endregion
    }
}
